Packages

In [1]:
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go

Visualization 1. malaria_inc.csv

The first plot is about Malaria incidence by country for all ages across the world across time.

You can single click the legend to delect the selected year, double click the legend to select the year they want to see, or move your cursor on the line to find the value corresponding to the cursor location.

In [2]:
inc = pd.read_csv("malaria_inc.csv")
inc.rename(columns={inc.columns[-1]: "Incidence of malaria (per 1,000 population at risk)"}, inplace=True)
inc.head()
Out[2]:
Entity Code Year Incidence of malaria (per 1,000 population at risk)
0 Afghanistan AFG 2000 107.100000
1 Afghanistan AFG 2005 46.500000
2 Afghanistan AFG 2010 23.900000
3 Afghanistan AFG 2015 23.600000
4 Algeria DZA 2000 0.037746
In [3]:
inc = inc[inc.iloc[:, 3] != 0]  # Countries with 0 cases don't need
In [4]:
inc = inc.sort_values(by=['Year', inc.columns[3]])
In [5]:
inc['Year'] = inc['Year'].astype(str) # parse coloumn: Year to string to enable caption/selector
In [6]:
fig = px.bar(
    inc,
    y='Entity',
    x=inc.columns[3],
    orientation='h',
    color='Year',
    color_discrete_map={
        '2000': '#1D2F6F', 
        '2005': '#8390FA', 
        '2010': '#6EAF46', 
        '2015': '#FAC748'
    }
)
fig.update_xaxes(title_text='Incidence of Malaria (per 1,000 population at risk)')
fig.update_yaxes(title_text='Entiry')
fig.update_layout(title_text='Malaria incidence by country for all ages across the world across time')
fig.show()

Visualization 2 malaria_deaths.csv

This plot maily shows the deaths of malaria by country across the world and time. The plot is like a colorful map. The darker the color is, the more people die.

There is an animation frames added to the plots, so you can view map plot in different year by changing the year. You can also move your cursor on different country to find the value corresponding to the cursor location.

In [7]:
death = pd.read_csv("malaria_deaths.csv")
death.head()
Out[7]:
Entity Code Year Deaths - Malaria - Sex: Both - Age: Age-standardized (Rate) (per 100,000 people)
0 Afghanistan AFG 1990 6.802930
1 Afghanistan AFG 1991 6.973494
2 Afghanistan AFG 1992 6.989882
3 Afghanistan AFG 1993 7.088983
4 Afghanistan AFG 1994 7.392472
In [8]:
death.rename(columns={death.columns[3]: "death"}, errors='raise', inplace=True)
In [9]:
fig = px.choropleth(
    death,
    locations="Code",
    color="death",  # lifeExp is a column of gapminder
    hover_name="Entity",  # column to add to hover information
    color_continuous_scale=px.colors.sequential.Teal,
    animation_frame="Year",
)
fig.update_layout(title_text='Malaria Deaths by Country across the World and Time')
fig.show()

Visualization 3 malaria_deaths_age.csv

This last plot shows the deaths of malaria by the country and the age.

There are two drop-down boxes to select the value, so the value shown in the figure will also change. If you want to view all the world and all ages, then just choose world and all in the two drop-down boxes. You can also move your cursor on different line part to find the value corresponding to the cursor location.

In [10]:
df = pd.read_csv("malaria_deaths_age.csv")
df.head()
Out[10]:
Unnamed: 0 entity code year age_group deaths
0 1 Afghanistan AFG 1990 Under 5 184.606435
1 2 Afghanistan AFG 1991 Under 5 191.658193
2 3 Afghanistan AFG 1992 Under 5 197.140197
3 4 Afghanistan AFG 1993 Under 5 207.357753
4 5 Afghanistan AFG 1994 Under 5 226.209363
In [11]:
df = df[df.deaths != 0] # Countries with 0 cases don't need
In [12]:
df.rename(columns={df.columns[3]: "num"}, errors='raise', inplace=True)
df.rename(columns={df.columns[1]: "label"}, errors='raise', inplace=True)
df.rename(columns={df.columns[4]: "color"}, errors='raise', inplace=True)
df.rename(columns={df.columns[5]: "value"}, errors='raise', inplace=True)
print(df.head())

df_input = df.copy()
   Unnamed: 0        label code   num    color       value
0           1  Afghanistan  AFG  1990  Under 5  184.606435
1           2  Afghanistan  AFG  1991  Under 5  191.658193
2           3  Afghanistan  AFG  1992  Under 5  197.140197
3           4  Afghanistan  AFG  1993  Under 5  207.357753
4           5  Afghanistan  AFG  1994  Under 5  226.209363
In [13]:
# split df by labels
dates = df['num'].unique().tolist()
labels = df['label'].unique().tolist()

# dataframe collection grouped by labels
dfs = {}
for label in labels:
    dfs[label] = pd.pivot_table(df[df['label'] == label],
                                values='value',
                                index=['num'],
                                columns=['color'],
                                aggfunc=np.sum)

# find row and column unions
common_cols = []
common_rows = []
for df in dfs.keys():
    common_cols = sorted(list(set().union(common_cols, list(dfs[df]))))
    common_rows = sorted(list(set().union(common_rows, list(dfs[df].index))))

# find dimensionally common dataframe
df_common = pd.DataFrame(np.nan, index=common_rows, columns=common_cols)

# reshape each dfs[df] into common dimensions
dfc = {}
for df_item in dfs:
    # print(dfs[unshaped])
    df1 = dfs[df_item].copy()
    s = df_common.combine_first(df1)
    df_reshaped = df1.reindex_like(s)
    dfc[df_item] = df_reshaped

# plotly start
fig = go.Figure()
# one trace for each column per dataframe: AI and RANDOM
for col in common_cols:
    fig.add_trace(go.Scatter(x=dates,
                             visible=True,
                             marker=dict(size=12, line=dict(width=2)),
                             marker_symbol='diamond', name=col
                             )
                  )

# menu setup
updatemenu = []

# buttons for menu 1, names
buttons = []

# create traces for each color:
# build argVals for buttons and create buttons
for df in dfc.keys():
    argList = []
    for col in dfc[df]:
        # print(dfc[df][col].values)
        argList.append(dfc[df][col].values)
    argVals = [{'y': argList}]

    buttons.append(dict(method='update',
                        label=df,
                        visible=True,
                        args=argVals))

# buttons for menu 2, colors
b2_labels = common_cols

# matrix to feed all visible arguments for all traces
# so that they can be shown or hidden by choice
b2_show = [list(b) for b in [e == 1 for e in np.eye(len(b2_labels))]]
buttons2 = []
buttons2.append({'method': 'update',
                 'label': 'All',
                 'args': [{'visible': [True] * len(common_cols)}]})

# create buttons to show or hide
for i in range(0, len(b2_labels)):
    buttons2.append(dict(method='update',
                         label=b2_labels[i],
                         args=[{'visible': b2_show[i]}]
                         )
                    )

# add option for button two to hide all
buttons2.append(dict(method='update',
                     label='None',
                     args=[{'visible': [False] * len(common_cols)}]
                     )
                )

# some adjustments to the updatemenus
updatemenu = []
your_menu = dict()
updatemenu.append(your_menu)
your_menu2 = dict()
updatemenu.append(your_menu2)
updatemenu[1]
updatemenu[0]['buttons'] = buttons
updatemenu[0]['direction'] = 'down'
updatemenu[0]['showactive'] = True
updatemenu[1]['buttons'] = buttons2
updatemenu[1]['y'] = 0.6
updatemenu[0]['x'] = -0.1
updatemenu[1]['x'] = -0.1

fig.update_layout(showlegend=True, updatemenus=updatemenu)
fig.update_layout(yaxis=dict(range=[0, df_input['value'].max() + 0.4]))


# button annotations
fig.update_layout(
    annotations=[
        dict(text="<i>Entity</i>", x=-0.4, xref="paper", y=1.1, yref="paper",
             align="left", showarrow=False, font=dict(size=16, color='steelblue')),
        dict(text="<i>Age_Group</i>", x=-0.4, xref="paper", y=0.7, yref="paper",
             align="left", showarrow=False, font=dict(size=16, color='steelblue')
             )],
    title_text='Malaria Deaths by Country and Age Group'
)

fig.show()
In [ ]: